#include <jni.h>
#include <string>

#include <android/log.h>

#include "lua/lua.hpp"

#define LUA_ERROR_TAG "LUA_ERROR"

using namespace std;

string toStdstring(JNIEnv* env, jstring javaStr) {
    auto src = env->GetStringUTFChars(javaStr, 0);

    string srcStr(src);

    env->ReleaseStringUTFChars(javaStr, src);

    return srcStr;
}

static lua_State* L = nullptr;

lua_State* getLuaState() {
    if (L == nullptr) {
        L = luaL_newstate();
        luaL_openlibs(L);
    }
    return L;
}

extern "C"
JNIEXPORT void JNICALL
Java_io_zerous_zexgraph_LuaMachine_initLuaInterpreter(JNIEnv *env, jobject instance) {
    getLuaState();
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_io_zerous_zexgraph_LuaMachine_luaLoadScript(JNIEnv *env, jobject instance,
                                                 jstring src_) {
    const char *src = env->GetStringUTFChars(src_, 0);

    auto L = getLuaState();

    luaL_loadstring(L, src);

    int failed = lua_pcall(L, 0, 0, 0);
    if (failed) {
        auto error = lua_tostring(L, -1);

        __android_log_write(ANDROID_LOG_ERROR, LUA_ERROR_TAG, error);
        lua_close(L);
        return JNI_FALSE;
    }

    env->ReleaseStringUTFChars(src_, src);

    return JNI_TRUE;
}

extern "C"
JNIEXPORT jfloat JNICALL
Java_io_zerous_zexgraph_LuaMachine_luaRun(JNIEnv *env, jobject instance, jfloat x) {
    lua_getglobal(L, "f");
    lua_pushnumber(L, x);
    int iRet = lua_pcall(L, 1, 1, 0);
    if (iRet) {
        auto error = lua_tostring(L, -1);

        __android_log_write(ANDROID_LOG_ERROR, LUA_ERROR_TAG, error);
        //lua_close(L);
    }

    float a = 0;
    if (lua_isnumber(L, -1)) {
        a = lua_tonumber(L, -1);
    }

    lua_settop(L, -2);
    return a;
}extern "C"
JNIEXPORT jfloat JNICALL
Java_io_zerous_zexgraph_LuaMachine_getOutputf(JNIEnv *env, jobject instance, jstring name_) {
    const char *name = env->GetStringUTFChars(name_, 0);



    env->ReleaseStringUTFChars(name_, name);
}